package cataletra.main;

import java.util.ArrayList;

public class CacaPalavras {

    public static final int INDEFINIDO = -1;
    public static final int NORTE = 0;
    public static final int NORDESTE = 1;
    public static final int LESTE = 2;
    public static final int SUDESTE = 3;
    public static final int SUL = 4;
    public static final int SUDOESTE = 5;
    public static final int OESTE = 6;
    public static final int NOROESTE = 7;
    private final String LETRAS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private ArrayList palavras;
    private int qtdeLinhas;
    private int qtdeColunas;
    private int qtdePalavras;
    private String[][] matriz;
    private java.util.Random random = new java.util.Random();
    private String[] palavrasUsadas;

    public CacaPalavras(ArrayList palavras, int qtdeLinhas, int qtdeColunas, int qtdePalavras) {
        this.palavras = (ArrayList) palavras.clone();
        this.qtdeLinhas = qtdeLinhas;
        this.qtdeColunas = qtdeColunas;
        this.qtdePalavras = qtdePalavras;
        this.palavrasUsadas = new String[qtdePalavras];

        matriz = new String[qtdeLinhas][qtdeColunas];

        for(int i = 0; i < qtdeLinhas; i++){
            for(int j = 0; j < qtdeColunas; j++){
                matriz[i][j] = "-";
            }
        }

        finalizaMatriz();
    }

    public static int getM(int posicao) {
        if(posicao <= 1 || posicao == 7){
            return -1;
        }
        if(posicao >= 3 && posicao <= 5){
            return 1;
        }
        return 0;
    }

    public static int getN(int posicao) {
        if(posicao >= 5){
            return -1;
        }
        if(posicao >= 1 && posicao <= 3){
            return 1;
        }
        return 0;
    }

    private void adicionaPalavra(String palavra, int x, int y, int posicao) {
        int m = getM(posicao);
        int n = getN(posicao);
        for(int i = 0; i < palavra.length(); i++){
            //System.out.println("x="+x+" i="+i+" m="+m+" y="+y+" n="+n);
            matriz[x + i * m][y + i * n] = palavra.substring(i, i + 1);
        }
    }

    private boolean cabeNaMatriz(String palavra, int x, int y, int posicao) {
        boolean cabe = false;

        if(posicao == NORTE){
            if(x + 1 - palavra.length() >= 0){
                cabe = true;
            }
        } else if(posicao == NORDESTE){
            if(x + 1 - palavra.length() >= 0 && y + 1 + palavra.length() < qtdeColunas){
                cabe = true;
            }
        } else if(posicao == LESTE){
            if(y + 1 + palavra.length() < qtdeColunas){
                cabe = true;
            }
        } else if(posicao == SUDESTE){
            if(x + 1 + palavra.length() < qtdeLinhas && y + 1 + palavra.length() < qtdeColunas){
                cabe = true;
            }
        } else if(posicao == SUL){
            if(x + 1 + palavra.length() < qtdeLinhas){
                cabe = true;
            }
        } else if(posicao == SUDOESTE){
            if(x + 1 + palavra.length() < qtdeLinhas && y + 1 - palavra.length() >= 0){
                cabe = true;
            }
        } else if(posicao == OESTE){
            if(y + 1 - palavra.length() >= 0){
                cabe = true;
            }
        } else if(posicao == NOROESTE){
            if(x + 1 - palavra.length() >= 0 && y + 1 - palavra.length() >= 0){
                cabe = true;
            }
        }

        return cabe;
    }

    private boolean encaixa(String palavra, int x, int y, int posicao) {
        int m = getM(posicao);
        int n = getN(posicao);
        boolean fit = cabeNaMatriz(palavra, x, y, posicao);

        //System.out.println("encaixa " + palavra + " pos=" + posicao + " x=" + x + " y=" + y);

        if(!fit){
            return false;
        }

        for(int i = 0; i < palavra.length(); i++){
            String letra = matriz[x + i * m][y + i * n];
            if(!palavra.substring(i, i + 1).equals(letra) && !letra.equals("-")){
                return false;
            }
        }

        return fit;
    }

    public boolean adiciona(String palavra, int posicao) {
        palavra = palavra.toUpperCase();
        int x = random.nextInt(qtdeLinhas - 1);
        int y = random.nextInt(qtdeLinhas - 1);

        for(int i = 0; i < qtdeLinhas * qtdeColunas; i++){
            if(encaixa(palavra, x, y, posicao)){
                adicionaPalavra(palavra, x, y, posicao);
                return true;
            } else {
                if(y + 1 < qtdeColunas){
                    y++;
                } else {
                    y = 0;
                    if(x + 1 < qtdeLinhas){
                        x++;
                    } else {
                        x = 0;
                    }
                }
            }
        }

        return false;
    }

    private void finalizaMatriz() {
        for(int i = 0; i < qtdePalavras; i++){
            int palavra = 0;
            palavra = random.nextInt(palavras.size());

            int pos = random.nextInt(8);
            //System.out.println("pos=" + pos);
            for(int g = 0; g < 8; g++){
                if(adiciona((String) palavras.get(palavra), pos)){
                    palavrasUsadas[i] = (String) palavras.get(palavra);
                    palavras.remove(palavra);
                    break;
                } else {
                    if(g == 7){
                        palavras.remove(palavra);
                        palavra = random.nextInt(palavras.size());
                        g = 0;
                    }
                    if(pos + 1 > 7){
                        pos = 0;
                    } else {
                        pos++;
                    }
                }
            }
        }

        for(int i = 0; i < qtdeLinhas; i++){
            for(int j = 0; j < qtdeColunas; j++){
                int x = random.nextInt(25);
                if(matriz[i][j].equals("-")){
                    matriz[i][j] = LETRAS.substring(x, x + 1);
                }
            }
        }
    }

    public String getLetra(int i, int j) {
        return matriz[i][j];
    }

    public int getLinhas() {
        return qtdeLinhas;
    }

    public int getColunas() {
        return qtdeColunas;
    }

    public String[] getPalavrasUsadas() {
        return palavrasUsadas;
    }

    public int getQtdePalavras() {
        return qtdePalavras;
    }

    public static int getPosicao(int[] inicio, int[] fim) {
        int pos = INDEFINIDO;

        if(fim[0] > inicio[0]){
            if(fim[1] > inicio[1]){
                pos = SUDESTE;
            } else if(fim[1] == inicio[1]){
                return SUL;
            } else {
                pos = SUDOESTE;
            }
        } else if(fim[0] == inicio[0]){
            if(fim[1] > inicio[1]){
                return LESTE;
            } else {
                return OESTE;
            }
        } else {
            if(fim[1] > inicio[1]){
                pos = NORDESTE;
            } else if(fim[1] == inicio[1]){
                return NORTE;
            } else {
                pos = NOROESTE;
            }
        }

        if(pos == SUDESTE && fim[0] - inicio[0] != fim[1] - inicio[1]){
            return INDEFINIDO;
        } else if(pos == SUDOESTE && fim[0] - inicio[0] != inicio[1] - fim[1]){
            return INDEFINIDO;
        } else if(pos == NORDESTE && inicio[0] - fim[0] != fim[1] - inicio[1]){
            return INDEFINIDO;
        } else if(pos == NOROESTE && inicio[0] - fim[0] != inicio[1] - fim[1]){
            return INDEFINIDO;
        }

        return pos;
    }

    //inicio[x][y] e fim[x][y]
    public String getPalavra(int posicao, int[] inicio, int[] fim) {
        String word = "";
        int tamanho = 0;

        if(posicao >= NORDESTE && posicao <= SUDESTE){
            tamanho = fim[1] - inicio[1];
        } else if(posicao >= SUDOESTE && posicao <= NOROESTE){
            tamanho = inicio[1] - fim[1];
        } else if(posicao == NORTE){
            tamanho = inicio[0] - fim[0];
        } else if(posicao == SUL){
            tamanho = fim[0] - inicio[0];
        }

        int m = getM(posicao);
        int n = getN(posicao);
        for(int i = 0; i < tamanho + 1; i++){
            word += matriz[inicio[0] + i * m][inicio[1] + i * n];
        }

        return word;
    }

    //0 é x, 1 é y e 2 é pos
    public int[] acharPalavra(String palavra) {
        int[] var = new int[3];
        String word = "";
        int m;
        int n;
        int x;
        int y;

        ArrayList posX = new ArrayList();
        ArrayList posY = new ArrayList();

        for(int i = 0; i < qtdeLinhas; i++){
            for(int j = 0; j < qtdeColunas; j++){
                if(matriz[i][j].equals(palavra.substring(0, 1))){
                    posX.add(i + "");
                    posY.add(j + "");
                }
            }
        }


        g:
        for(int i = 0; i < posX.size(); i++){
            x = Integer.parseInt((String) posX.get(i));
            y = Integer.parseInt((String) posY.get(i));
            for(int p = 0; p < 8; p++){
                m = getM(p);
                n = getN(p);

                if(!cabeNaMatriz(palavra, x, y, p)) {
                    continue;
                }

                for(int t = 0; t < palavra.length(); t++){
                    word += matriz[(t * m) + x][(t * n) + y];
                }

                if(word.equals(palavra.toUpperCase())){
                    var[0] = x;
                    var[1] = y;
                    var[2] = p;
                    break g;
                }

                word = "";
            }
        }


        return var;
    }
}